
package com.jf.cloud.order.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jf.cloud.api.delivery.feign.StationFeignClient;
import com.jf.cloud.api.delivery.vo.StationVO;
import com.jf.cloud.api.feign.SearchOrderFeignClient;
import com.jf.cloud.api.order.constant.OrderStatus;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.order.constant.OrderActivityType;
import com.jf.cloud.common.order.dto.OrderSearchDTO;
import com.jf.cloud.common.order.vo.*;
import com.jf.cloud.order.constant.RefundStatusEnum;
import com.jf.cloud.order.mapper.OrderSelfStationMapper;
import com.jf.cloud.order.model.OrderSelfStation;
import com.jf.cloud.order.service.OrderItemService;
import com.jf.cloud.order.service.OrderSelfStationService;
import com.jf.cloud.order.service.OrderVirtualInfoService;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自提订单自提点信息
 *
 * @author zz
 * @date 2020-12-05 14:13:50
 */
@Service
public class OrderSelfStationServiceImpl implements OrderSelfStationService {

    @Autowired
    private OrderSelfStationMapper orderSelfStationMapper;

    @Autowired
    private StationFeignClient stationFeignClient;
    @Autowired
    private SearchOrderFeignClient searchOrderFeignClient;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private OrderVirtualInfoService orderVirtualInfoService;

    /**
     * 默认地球半径
     */
    private static double EARTH_RADIUS = 6371000;//赤道半径(单位m)

    @Override
    public PageVO<OrderSelfStationVO> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> orderSelfStationMapper.list());
    }

    @Override
    public OrderSelfStationVO getById(Long id) {
        return orderSelfStationMapper.getById(id);
    }

    @Override
    public void save(OrderSelfStation orderSelfStation) {
        orderSelfStationMapper.save(orderSelfStation);
    }

    @Override
    public void update(OrderSelfStation orderSelfStation) {
        orderSelfStationMapper.update(orderSelfStation);
    }

    @Override
    public void deleteById(Long id) {
        orderSelfStationMapper.deleteById(id);
    }

    @Override
    public List<OrderSelfStation> getStationUserInfo(Long userId) {
        return orderSelfStationMapper.getStationUserInfo(userId);
    }

    @Override
    public OrderVO getOrderByStationCode(Long stationId, String code) {
        //OrderVO orderByStationCode = orderSelfStationMapper.getOrderByStationCode(stationId, code);
        StationVO stationVO = stationFeignClient.getStation(stationId).getData();
        OrderSearchDTO orderSearchDTO = new OrderSearchDTO();
        orderSearchDTO.setPageSize(1);
        orderSearchDTO.setPageNum(1);
        orderSearchDTO.setStatus(OrderStatus.PAYED.value());
        orderSearchDTO.setStationCode(code);
        orderSearchDTO.setStationId(stationId);
        orderSearchDTO.setShopId(stationVO.getShopId());
        List<EsOrderVO> orderList = searchOrderFeignClient.listEsOrder(orderSearchDTO).getData();
        if (Objects.isNull(orderList) || orderList.size() == 0) {
            orderSearchDTO = new OrderSearchDTO();
            orderSearchDTO.setPageSize(1);
            orderSearchDTO.setPageNum(1);
            orderSearchDTO.setStatusList(Arrays.asList(
                    OrderStatus.CONSIGNMENT.value(),
                    OrderStatus.SUCCESS.value())
            );
            orderSearchDTO.setWriteOffStatus(0);
            orderSearchDTO.setOrderMold(1);
            orderSearchDTO.setWriteOffCode(code);
            orderSearchDTO.setShopId(stationVO.getShopId());
            // 如果查询不到，就去查询虚拟商品的券码信息
            orderList = searchOrderFeignClient.listEsOrder(orderSearchDTO).getData();
            if (Objects.isNull(orderList) || orderList.size() == 0) {
                throw new LuckException("该提货码，没有对应的订单");
            } else {
                List<OrderVirtualInfoVO> orderVirtualInfoVOList = orderVirtualInfoService.getByOrderIdAndCode(orderList.get(0).getOrderId(), code);
                if (Objects.nonNull(orderVirtualInfoVOList) ) {
                    List<OrderVirtualInfoVO> infoList = orderVirtualInfoVOList.stream().filter(infoVO -> infoVO.getIsWriteOff() == 0).collect(Collectors.toList());
                    if (infoList.size() == 0) {
                        throw new LuckException("该提货码，没有对应的订单");
                    }
                    orderList.get(0).setOrderVirtualInfoList(infoList);
                }
            }
        }else if (Objects.equals(orderList.get(0).getRefundStatus(), RefundStatusEnum.SUCCEED.value())){
            // 该提货码，没有对应的订单
            throw new LuckException("该提货码，没有对应的订单");
        }
        OrderVO orderByStationCode = mapperFacade.map(orderList.get(0), OrderVO.class);
        if (Objects.isNull(stationId)) {
            return orderByStationCode;
        }
        if (StrUtil.isBlank(orderByStationCode.getShopName())) {
            orderByStationCode.setShopName(Constant.PLATFORM_SHOP_NAME);
        }
        orderByStationCode.setOrderSelfStationVO(orderSelfStationMapper.getStationByOrderId(orderByStationCode.getOrderId()));
        Map<Long, List<OrderItemVO>> giveawayMap = orderByStationCode.getOrderItems().stream().filter(orderItemVO -> Objects.equals(orderItemVO.getActivityType(), OrderActivityType.GIVEAWAY.value()))
                .collect(Collectors.groupingBy(OrderItemVO::getActivityId));
        if (MapUtil.isNotEmpty(giveawayMap)) {
            Iterator<OrderItemVO> iterator = orderByStationCode.getOrderItems().iterator();
            while (iterator.hasNext()) {
                OrderItemVO orderItem = iterator.next();
                if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value())) {
                    iterator.remove();
                }
                orderItem.setGiveawayList(giveawayMap.get(orderItem.getOrderItemId()));
            }
        }
        return orderByStationCode;
    }

    @Override
    public OrderSelfStationVO getStationByOrderId(Long orderId) {

        OrderSelfStationVO stationByOrderId = orderSelfStationMapper.getStationByOrderId(orderId);
        if (Objects.isNull(stationByOrderId)) {
            throw new LuckException("订单不存在");
        }
        StationVO stationVO = stationFeignClient.getStation(stationByOrderId.getStationId()).getData();
        stationByOrderId.setStationName(stationVO.getStationName());
        stationByOrderId.setLat(stationVO.getLat());
        stationByOrderId.setLng(stationVO.getLng());
        stationByOrderId.setTimeInfo(stationVO.getTimeInfo());
        stationByOrderId.setStationStatus(stationVO.getStatus());
        stationByOrderId.setStationImgUrl(stationVO.getImgUrl());
        // 自提点营业时间
        String timeDate = stationByOrderId.getTimeInfo();
        JSONObject jsonObject = JSON.parseObject(timeDate);
        Object shopTime = jsonObject.get("shopTime");
        JSONArray objects = JSON.parseArray(shopTime.toString());
        // 时间戳->时间格式
        String startTimePoke = objects.get(0).toString();
        String endTimePoke = objects.get(1).toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String startTime = sdf.format(Long.valueOf(startTimePoke)).substring(11);
        String endTime = sdf.format(Long.valueOf(endTimePoke)).substring(11);
        // 自提点营业时间(不包含月和日)
//        String time = startTime + "-" + endTime;
//        StringBuffer stringBuffer = new StringBuffer(stationByOrderId.getStationTime());
//        // 订单自中提点时间读取最新的自提点营业时间
//        // 时间格式是 xx月xx日 00:00-00:00 例如01月01日 01:00-02:00
//        if (stringBuffer.length() == 18){
//            stringBuffer.replace(7,18,time);
//        }
//        // 时间格式是 xx月xx日 早上/下午/晚上(00:00-00:00) 例如 01月01日 早上(10:00-11:00)
////        if (stringBuffer.length() == 22){
////            stringBuffer.replace(10,21,time);
////        }
//        // 时间格式是 xx-xx 00:00-00:00 例如 01-01 10:00-11:00
//        if (stringBuffer.length() == 17){
//            stringBuffer.replace(6, 17, time);
//        }
//        stationByOrderId.setStationTime(stringBuffer.toString());
        return stationByOrderId;
    }

    @Override
    public Double setStationDistance(Long stationId, Double lat, Double lng) {
        StationVO stationVO = stationFeignClient.getStation(stationId).getData();
        return GetDistance(lng, lat, stationVO.getLng(), stationVO.getLat());
    }

    @Override
    public List<OrderSelfStationVO> getUserStation(Long userId) {
        return orderSelfStationMapper.getUserStation(userId);
    }

    @Override
    public List<OrderSelfStationVO> listSelfStationByOrderIds(List<Long> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return new ArrayList<>();
        }
        List<OrderSelfStationVO> orderSelfStationVOS = orderSelfStationMapper.listSelfStationByOrderIds(orderIds);
        return orderSelfStationVOS;
    }

    @Override
    public List<OrderSelfStationVO> getOrderSelfStationByStationIdOrShopId(Long userId, Long stationId, Long shopId) {
        return orderSelfStationMapper.getOrderSelfStationByStationIdOrShopId(userId, stationId, shopId);
    }

    /**
     * 转化为弧度(rad)
     */
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * @param lon1 第一点的精度
     * @param lat1 第一点的纬度
     * @param lon2 第二点的精度
     * @param lat2 第二点的纬度
     * @return 返回的距离，单位m
     */
    private static double GetDistance(double lon1, double lat1, double lon2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lon1) - rad(lon2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }
}
